package com.xiguanlezz.cn.client.naming.core;

import com.xiguanlezz.cn.api.PropertyKeyConst;
import com.xiguanlezz.cn.client.env.NacosClientProperties;
import com.xiguanlezz.cn.common.remote.client.ServerListFactory;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Author：习惯了种种
 * @CreateDate：2024/11/16 17:41
 * @Description：Nacos服务端地址管理类
 */
public class ServerListManager implements ServerListFactory {
    // 每个namespace都有单独的NacosNamingService，故NacosNamingService中依赖的Nacos服务端地址管理类当然也和namespace绑定
    private String namespace;

    // 这个索引和serverList配合即可达到：在Nacos集群部署时访问的伪负载均衡的效果
    private AtomicInteger idx = new AtomicInteger();

    // 为什么不需要使用并发安全的List？因为这个列表除了初始化，后面都是由某个定时任务的单线程去更新的，不存在并发安全问题
    private volatile List<String> serverList = new ArrayList<>();


    public ServerListManager(String namespace, NacosClientProperties properties) {
        this.namespace = namespace;

        // 读取配置文件中配置的Nacos服务端地址
        initServerAddr(properties);

        List<String> serverList = getServerList();
        if (CollectionUtils.isEmpty(serverList)) {
            throw new RuntimeException("serverList is empty, please check config...");
        } else {
            // 首次启动随机打乱index
            idx.set(ThreadLocalRandom.current().nextInt(serverList.size()));
        }
    }

    private void initServerAddr(NacosClientProperties properties) {
        String serverListFromProps = properties.getProperty(PropertyKeyConst.SERVER_ADDR);
        if (StringUtils.isNotEmpty(serverListFromProps)) {
            this.serverList.addAll(Arrays.asList(serverListFromProps.split(",")));
        }
        // TODO(xiguanlezz): 定时更新serverList
    }

    @Override
    public String genNextServer() {
        int curIdx = idx.incrementAndGet() % getServerList().size();
        return getServerList().get(curIdx);
    }

    @Override
    public String getCurrentServer() {
        return getServerList().get(idx.get() % getServerList().size());
    }

    @Override
    public List<String> getServerList() {
        return serverList;
    }
}
